home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Design
/
WB Collection.iso
/
workbench werkzeuge
/
scherz programme
/
fortune
/
source
/
readfort.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-07
|
36KB
|
1,569 lines
/* Source Control
$RCS
$version 3.25
$date Wed Mar 03 17:53:36 1993
$changes :
Revision 3.25 Jim Wed Mar 03 17:53:36 1993
Rewrote the QUIT stuff for Brian Sutherland
Revision 3.24 Jim Wed Jul 15 00:47:06 1992
Faster disk access, and priority niced up during disk acess/decompression
Revision 3.23 Jim Mon Mar 16 14:13:22 1992
Supports reqtools.library
Revision 3.22 Jim Fri Dec 06 18:01:04 1991
Alarm clock added
Revision 3.21 Jim Fri Dec 06 12:10:30 1991
Clock/memory monitor functions added
Revision 3.20 Jim Thu Dec 05 21:24:08 1991
Timer device supported
Revision 3.19 Jim Thu Dec 05 19:23:31 1991
Pause and Iconify gadgets added
Revision 3.18 Jim Mon Oct 14 12:16:59 1991
Gadgets added (registered users only!!)
Revision 3.17 Jim Wed Aug 14 16:00:54 1991
-q and QUIT options added (suggested by D.R. Daines)
Revision 3.16 Jim Sun Aug 11 15:15:44 1991
Ftext bug fixed- reads extended ascii
Revision 3.15 Jim Wed Aug 07 18:47:44 1991
Restored
Revision 3.14 Jim Wed Aug 07 18:12:03 1991
Special version
Revision 3.13 Jim Wed Aug 07 18:07:23 1991
No change
Revision 3.12 Jim Sun Aug 04 03:05:49 1991
bug in WriteFortune fixed. Used to crash if device not mounted.
Revision 3.11 Jim Wed Jul 17 15:23:15 1991
bug fixed with long flags
Revision 3.10 Jim Tue Jul 16 15:19:29 1991
Fortune number can be specified (suggested by Leigh Barlow)
Revision 3.9 Jim Sun Jul 14 15:23:00 1991
Better error handling - error window opened if on WB
Revision 3.8 Jim Tue Jul 09 18:16:56 1991
-x and -y flags added, -p kept for compatability
Revision 3.7 Jim Sat Jun 29 22:10:28 1991
Adaptive huffman code used
Revision 3.6 Jim Tue Jun 11 15:02:43 1991
coloured backgrounds (oh dear.. what is this, gfortune?)
Revision 3.5 Jim Tue Jun 11 14:41:03 1991
Now allows for WB larger than normal.
Revision 3.4 Jim Sat Jun 01 20:34:35 1991
Now fortunes printed directly with graphics drivers (AF Coverdisk version)
Revision 3.3 Jim Sat Jun 01 20:34:14 1991
More tidying up
Revision 3.2 Jim Sat Jun 01 10:33:28 1991
various tidying up, width support, fonts etc.
Revision 3.1 Jim Fri May 31 13:29:21 1991
tooltypes DELAY and FLAGS added
Revision 3.0 Jim Fri May 31 12:20:37 1991
speak, print and key support; plus better help.
Revision 2.2 Jim Fri May 31 11:40:18 1991
Now with WB interface
Revision 2.1 Jim Thu May 23 21:09:52 1991
Now works under 2.0
Revision 2.0 Jim Mon Sep 10 19:22:17 1990
Added to RCS
*/
/*
Fortune Cookie Printer. Takes cookies from a file given in the
command line, or "fortunes" if no file is given. The file
is in the format produced by makefort.
Written by J. Finnis, 1990-1991.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <libraries/dos.h>
#include <libraries/reqtools.h>
#include <devices/timer.h>
#include <devices/audio.h>
#include <proto/all.h>
#include <proto/reqtools.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include <time.h>
#define TIMELIM 10
#define ICONLEN 350
#define ICONTITLE "Fortune 3.25 by J.Finnis"
#define MINWIDTH 350
#define TINYICONLEN 160
#define CLOCKLEN 150
#define MAXSIZE 1000
#define XOFFSET (MINWIDTH-125)
#define TINYXOFFSET 21
#define CF_CLOCK 1 /* show time */
#define CF_TOTALMEM 2 /* show total memory */
#define CF_ALLMEM 4 /* show memory as chip/fast */
#define CF_DATE 8 /* show date */
static char *month_names[]=
{
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct",
"Nov","Dec"
};
static UBYTE whichannel[]={1,2,4,8};
static struct IOAudio *AIOPtr=NULL;
static struct MsgPort *audioport=NULL;
#define SOUND_LEN 934
static UWORD chip SoundData[]={
0x0,0x0,0x800,0xee,0xf2eb,0xf5f2,0xebf0,0xebe5,
0xf1f5,0xf901,0x507,0x909,0xe0e,0x1214,0xc07,0x1210,
0x1926,0x1a22,0x2415,0x1d14,0xc0e,0x404,0xfffc,0xfef4,
0xf1f1,0xecec,0xe8e2,0xe1de,0xe0dc,0xe2ec,0xeefb,0xfd02,
0x1117,0x14fb,0xdfd5,0xc1b6,0xc9e9,0xf909,0x1d1a,0x1b26,
0x3c5b,0x6670,0x7736,0x6e8,0xb0b4,0xc5dc,0x212,0x222e,
0x1b1b,0x1cfd,0xf4f0,0xd4d2,0xdcdc,0xebf3,0xf9f9,0xeee2,
0xc380,0x8299,0xc104,0x6d7f,0x7f7f,0x6f0d,0xdbc5,0xd7d4,
0xdf04,0xf2f7,0x2841,0x4d73,0x4c1b,0xe6b9,0xb5b9,0xd9fd,
0x151a,0x2925,0xfff2,0xe5b5,0x8f81,0x8294,0xca12,0x7f7f,
0x7f7f,0x2fc6,0x8e91,0xcad1,0xef1a,0x2f49,0x637f,0x501a,
0xf5c1,0xa9cf,0xfa02,0x1926,0x1f14,0x80a,0xfbea,0xc783,
0x8182,0x9bfa,0x747f,0x7f7f,0x12af,0x8083,0xb706,0x232f,
0x3c4e,0x5262,0x5f19,0xd6b7,0xc0d3,0x92d,0x261a,0x4fc,
0xfffc,0x1717,0xec95,0x8082,0x8dda,0x6c7f,0x7f71,0xea8e,
0x8182,0xc61a,0x3627,0x2c37,0x4475,0x6733,0xddaa,0xb7cc,
0x1742,0x3c1f,0xfef4,0xe80b,0x2828,0x17b4,0x8083,0x83d3,
0x607f,0x7f7e,0xf880,0x8483,0xe329,0x3a28,0x112f,0x5278,
0x6a32,0xd596,0xb1db,0x2753,0x471a,0xe7dc,0xde06,0x2730,
0x1fbf,0x8082,0x85da,0x5e7f,0x7f62,0xd580,0x8bab,0x739,
0x2905,0xf922,0x4660,0x520f,0xb58d,0xbdf9,0x324c,0x32f7,
0xcbd6,0xea10,0x2f31,0xb9c,0x8083,0x9d03,0x7f7f,0x7f2c,
0x9d80,0x9ae4,0x2b3d,0x1d06,0xd32,0x5a65,0x27e2,0xab9d,
0xe92a,0x5841,0x16de,0xb7e4,0x221,0x3228,0xd780,0x818d,
0xc249,0x7f7f,0x5fce,0x8095,0xc71f,0x4824,0xc0d,0x2056,
0x6957,0xf4b8,0xa8d2,0x1557,0x591c,0xeec3,0xd600,0x2c38,
0x2cf4,0x8480,0x82be,0x277f,0x7f74,0xea8d,0x9ac7,0x955,
0x3901,0x61a,0x3d5c,0x6a13,0xc3af,0xccfe,0x4863,0x3bf1,
0xcddb,0xf129,0x433b,0x697,0x8083,0xa30e,0x7f7f,0x79f0,
0x8290,0xcaff,0x5444,0x5e7,0xb37,0x4b69,0x23c3,0x96b5,
0xff35,0x5e45,0xeabc,0xc3ee,0x2242,0x4a19,0xa180,0x839f,
0x77d,0x7f6f,0xe881,0x88c7,0x24e,0x3d0c,0xe80b,0x434f,
0x5830,0xcb97,0xb8fe,0x3360,0x4d00,0xc1c4,0xe815,0x444f,
0x29b2,0x8083,0x8cf5,0x787f,0x76f2,0x8080,0xafee,0x3f34,
0x12f2,0x237,0x455e,0x33e1,0xa2ab,0xf11f,0x4f59,0x18da,
0xccdd,0x630,0x4a36,0xe580,0x8087,0xe45c,0x7f7f,0x31a8,
0x85b8,0xd728,0x3b1a,0xf702,0x3444,0x5033,0x4bc,0xbdea,
0x1237,0x3d21,0xebcf,0xe2ff,0x1f33,0x33f5,0x8480,0x85d3,
0x3a7f,0x7f4a,0xc98a,0xb4cc,0x1835,0x3208,0x35,0x383e,
0x4011,0xd0af,0xe305,0x284c,0x3cfb,0xcfd9,0xef11,0x3d44,
0x16b0,0x8083,0xac07,0x777f,0x6ef8,0x848d,0xaef2,0x3336,
0x21e9,0xff1f,0x3048,0x2af2,0xb3ad,0xde0e,0x3e47,0x22dc,
0xc0da,0xff28,0x3e31,0xee89,0x8083,0xd439,0x7f7f,0x48bd,
0x80a2,0xc313,0x413d,0xfe8,0x1123,0x3c3f,0x1ff1,0xadc9,
0xec17,0x322c,0x19dc,0xd5eb,0x420,0x2928,0xe084,0x8191,
0xed45,0x7f7f,0x3cc2,0x93b2,0xcb10,0x2f3b,0x14ff,0x2420,
0x3131,0x1bf2,0xd5ed,0xfc17,0x2b28,0xeed,0xedee,0x621,
0x2926,0xe48a,0x819f,0xed44,0x7f7d,0x44d7,0xb2b5,0xc8fe,
0x1533,0x160f,0x2415,0x1e19,0x12fc,0xec03,0x717,0x1c15,
0x6ec,0xedf1,0x213,0x1919,0xf3ab,0x81b8,0xef2c,0x667a,
0x5b08,0xdcc1,0xb4d6,0xe70d,0xd19,0x2a1d,0x150c,0x7f7,
0xe6f9,0xf4f8,0xfcfd,0xfefd,0x403,0x305,0xf2eb,0xdfb6,
0x95cb,0xf315,0x4660,0x602c,0xfef6,0xe6f0,0xfa04,0x40c,
0x2016,0x909,0xb10,0x80f,0xafd,0xf3e5,0xdce9,0xf7fe,
0xb0d,0x3f5,0xddd5,0xe8f5,0xa1c,0x251f,0x1504,0xf0e8,
0xf2ff,0x40d,0x1303,0xfc00,0x203,0x106,0xc03,0x311,
0x1914,0x120e,0x40c,0x904,0xa09,0x309,0xd06,0x609,
0xd07,0x8,0x1200,0xf805,0xd07,0x806,0x20b,0x703, 0xa0c,0x0,0x0,0x0
};
int colour=0;
int Again=FALSE;
int Ticks=0,back=0,speak=0,print=0,longflag=0,win=0;
int del=-1,clockpos;
int iy,ix=300,tiny=0;
ULONG clock=0L;
LONG olddir=-1;
char *internal="Internal error: %d\n";
char *Version="
Fortune
vrsn 3.25 by Jim Finnis, Mar 1993\n";
struct TextFont *topazfont,*sysfont,*customfont=NULL;
#define IDCMPFLAGS GADGETDOWN|VANILLAKEY|NEWSIZE|CLOSEWINDOW
static UWORD chip LeftGadgData[]={
0xffff,0xffff,0xefff,0xc001,0x8001,
0x8001,0xc001,0xefff,0xffff,0xffff,
0xf7ff,0xe7ff,0xc000,0x8000,0x0,
0x0,0x8000,0xc000,0xe7ff,0xf7ff
};
static UWORD chip RandGadgData[]={
0xffff,0x8001,0x9c71,0x8209,0x8c31,
0x8001,0x8821,0x8001,0x8001,0xffff,
0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0
};
static UWORD chip RightGadgData[]={
0xffff,0xffff,0xfff7,0x8003,0x8001,
0x8001,0x8003,0xfff7,0xffff,0xffff,
0xffef,0xffe7,0x3,0x1,0x0,
0x0,0x1,0x3,0xffe7,0xffef
};
static UWORD chip IconifyGadgData[]={
0x7ffe,0x7ffe,0x6e76,0x6246,0x6006,
0x6006,0x6246,0x6e76,0x7ffe,0x7ffe,
0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0
};
static UWORD chip PauseGadgData[]={
0x7ffe,0x7ffe,0x783e,0x799e,0x799e,
0x783e,0x79fe,0x79fe,0x7ffe,0x7ffe,
0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0
};
static struct Image RandImage={0,0,16,10,2,RandGadgData,3,0,NULL};
static struct Image RightImage={0,0,16,10,2,RightGadgData,3,0,NULL};
static struct Image LeftImage={0,0,16,10,2,LeftGadgData,3,0,NULL};
static struct Image PauseImage={0,0,16,10,2,PauseGadgData,3,0,NULL};
static struct Image IconifyImage={0,0,16,10,2,IconifyGadgData,3,0,NULL};
static struct Gadget RightGadg={NULL,0,0,16,10,
GADGIMAGE|GADGHCOMP,RELVERIFY|GADGIMMEDIATE|TOPBORDER,
BOOLGADGET,(APTR)&RightImage,NULL,NULL,NULL,
NULL,2,NULL};
static struct Gadget RandGadg={&RightGadg,0,0,16,10,
GADGIMAGE|GADGHCOMP,RELVERIFY|GADGIMMEDIATE|TOPBORDER,
BOOLGADGET,(APTR)&RandImage,NULL,NULL,NULL,
NULL,1,NULL};
static struct Gadget PauseGadg={&RandGadg,0,0,16,10,
GADGIMAGE|GADGHCOMP,TOGGLESELECT|RELVERIFY|GADGIMMEDIATE|TOPBORDER,
BOOLGADGET,(APTR)&PauseImage,NULL,NULL,NULL,
NULL,3,NULL};
static struct Gadget IconifyGadg={&PauseGadg,0,0,16,10,
GADGIMAGE|GADGHCOMP,RELVERIFY|GADGIMMEDIATE|TOPBORDER,
BOOLGADGET,(APTR)&IconifyImage,NULL,NULL,NULL,
NULL,4,NULL};
static struct Gadget LeftGadg={&IconifyGadg,0,0,16,10,
GADGIMAGE|GADGHCOMP,RELVERIFY|GADGIMMEDIATE|TOPBORDER,
BOOLGADGET,(APTR)&LeftImage,NULL,NULL,NULL,
NULL,0,NULL};
static struct NewWindow ConNewWindow=
{
0,0, /*Window posn*/
0,0, /*Width+height*/
-1,-1, /*detailpen, blockpen*/
IDCMPFLAGS,
NOCAREREFRESH|SMART_REFRESH|ACTIVATE|WINDOWCLOSE|
WINDOWDEPTH|WINDOWDRAG,
NULL, /* first gadget (we add them with AddGList()) */
NULL, /*checkmark*/
NULL, /*window title*/
NULL, /*screen*/
NULL, /*bitmap*/
120,50, /*minsize*/
640,200, /*maxsize*/
WBENCHSCREEN
};
extern void loadhuffman(BPTR);
extern char *uncompress(char *);
extern long readlong(BPTR);
extern void readstring(char *,int,BPTR); /* buf len file */
char *infile="fortunes";
struct IntuitionBase *IntuitionBase=NULL;
struct GfxBase *GfxBase=NULL;
struct ReqToolsBase *ReqToolsBase=NULL;
struct Library *IconBase=NULL;
struct Library *DiskfontBase=NULL;
VOID CreateConsole();
VOID CleanUpAndExit();
struct Screen *ConsoleScreen=NULL;
struct Window *ConsoleWindow=NULL;
LONG ConsoleOpen=FALSE;
int CXBRK(VOID)
{
return(0);
}
int wb_exec=1;
static int stolen=0,req=0;
static long old_priority=0;
#define HIGH_PRI 3
void NiceUp(void)
{
old_priority=SetTaskPri(FindTask(NULL),HIGH_PRI);
}
void NiceDown(void)
{
SetTaskPri(FindTask(NULL),old_priority);
}
void Panic(int fatal,char *s,...)
{
va_list argptr;
char buf[80];
FILE *a;
va_start(argptr,s);
vsprintf(buf,s,argptr);
va_end(argptr);
NiceDown();
if(win)
{
if(ReqToolsBase)
{
rtEZRequest(buf,"Oh dear",NULL,NULL);
}
else
{
if(a=fopen("CON:0/0/640/40/Message","r+"))
{
fprintf(a,buf);
Delay(3*TICKS_PER_SECOND);
fclose(a);
}
}
}
else
{
if(a=fopen("*","r+"))
{
fputs(buf,a);
fclose(a);
}
}
if(fatal)CleanUpAndExit();
}
/*
* Audio stuff for the alarm
*
*/
static void SND_Ready(void)
{
if(AIOPtr) /* If there's an IO running, abort it */
{
if(req && !CheckIO((struct IORequest *)AIOPtr))
{
AbortIO((struct IORequest *)AIOPtr);
Wait(1L << audioport->mp_SigBit);
}
if(GetMsg(audioport)) /* if there's a reply waiting */
{
switch(AIOPtr->ioa_Request.io_Error) /* check for error */
{
case 0: /* No error */
break;
case ADIOERR_NOALLOCATION:
stolen=1;
break;
default:
Panic(1,"bad channel audio command reply");
}
}
req=0;
}
}
static ULONG device=1;
static long clockfreq;
static void SND_Shutdown(void)
{
SND_Ready();
if(audioport)DeletePort(audioport);
if(!device)CloseDevice((struct IORequest *)AIOPtr);
if(AIOPtr)FreeMem(AIOPtr,sizeof(struct IOAudio));
}
static void SND_SetupAllocate(void)
{
AIOPtr->ioa_Request.io_Message.mn_ReplyPort=audioport;
/* Priority 70 is above most stuff, but still below the MEDplayer
(which is 127) */
AIOPtr->ioa_Request.io_Message.mn_Node.ln_Pri=70;
AIOPtr->ioa_Request.io_Command=ADCMD_ALLOCATE;
AIOPtr->ioa_Request.io_Flags=ADIOF_NOWAIT;
AIOPtr->ioa_AllocKey=0;
AIOPtr->ioa_Data=whichannel;
AIOPtr->ioa_Length=sizeof(whichannel);
}
static int SND_ReAllocate(void)
{
SND_SetupAllocate();
stolen=0;
return(DoIO((struct IORequest *)AIOPtr));
}
static void SND_Init(void)
{
if(!GfxBase)Panic(1,"sound: wot no GfxBase?")
clockfreq= (GfxBase->DisplayFlags & PAL) ? 3546895 : 3579545;
if(!(audioport=CreatePort(0,0)))Panic(1,"sound: can't allocate port");
if(!(AIOPtr=AllocMem(sizeof(struct IOAudio),MEMF_CLEAR|MEMF_PUBLIC)))
Panic(1,"sound: can't allocate iorequest");
SND_SetupAllocate();
if(device=OpenDevice("audio.device",0L,(struct IORequest *)AIOPtr,0L))
Panic(1,"can't open audio device");
}
void SND_Play(char *data,ULONG len,int period)
{
/* This is the PLAY function */
SND_Ready(); /* abort any running sound and pending replies */
/* Check if our channel was stolen last time */
if(stolen) /* Attempt to reallocate */
{
if(SND_ReAllocate())return;
}
AIOPtr->ioa_Request.io_Message.mn_ReplyPort =audioport;
AIOPtr->ioa_Request.io_Command=CMD_WRITE;
AIOPtr->ioa_Request.io_Flags=ADIOF_PERVOL;
AIOPtr->ioa_Data=data;
AIOPtr->ioa_Length=len;
AIOPtr->ioa_Period=period;
AIOPtr->ioa_Volume=64;
AIOPtr->ioa_Cycles=1;
BeginIO((struct IORequest *)AIOPtr);
req=1;
}
/*
* Version 3.20 : Timer device stuff.
*
*/
struct timerequest *timermsg=NULL;
struct MsgPort *timerport=NULL;
int timeropen=0;
/* Set up a 1 second timer request */
void TimerGo(void)
{
timermsg->tr_node.io_Command=TR_ADDREQUEST;
timermsg->tr_time.tv_secs=1;
timermsg->tr_time.tv_micro=0;
timermsg->tr_node.io_Message.mn_ReplyPort=timerport;
SendIO((struct IORequest *)timermsg);
}
/* Allocate and open the timer device, and fire off the first 1 second
request. */
void StartTimerDevice(void)
{
if(!(timermsg=(struct timerequest *)
AllocMem(sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR)))
Panic(1,"no memory for time request");
timermsg->tr_node.io_Message.mn_Node.ln_Type=NT_MESSAGE;
timermsg->tr_node.io_Message.mn_Node.ln_Pri=0;
timermsg->tr_node.io_Message.mn_Node.ln_Name=NULL;
if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)timermsg,0))
Panic(1,"unable to open timer device");
timeropen=1;
if(!(timerport=CreatePort(0,0)))
Panic(1,"unable to open timer port");
/* Fire off the first request */
TimerGo();
}
void TimerStop(void)
{
if(timerport && !CheckIO((struct IORequest *)timermsg))
{
AbortIO((struct IORequest *)timermsg);
WaitIO((struct IORequest *)timermsg);
}
if(timerport)DeletePort(timerport);
if(timeropen)CloseDevice((struct IORequest *)timermsg);
if(timermsg)FreeMem(timermsg,sizeof(struct timerequest));
}
/*
*
*
*/
int GetTextLength(struct TextFont *t,char *s)
{
UWORD width=0;
char c;
int addkern,addspace,kern,space;
addkern = t->tf_CharKern ? TRUE : FALSE;
addspace= t->tf_CharSpace ? TRUE : FALSE;
for(;*s;s++)
{
c= *s-t->tf_LoChar;
kern=((UWORD *)(t->tf_CharKern))[c];
space=((UWORD *)(t->tf_CharSpace))[c];
if(addspace)
width+=space;
else
width+=t->tf_XSize;
if(addkern)
width+=kern;
}
width+=5;
return((int)width);
}
int GetMaxTextLen(struct TextFont *font,char *str)
{
char *i,*j;
int t1=0,t2;
for(i=str,j=str;;j++)
{
if(*j=='\n'||!*j)
{
char c;
c=*j; *j=0;
t2=GetTextLength(font,i);
t1=max(t2,t1);
if(!(*(i=j)=c))break;
i++;
}
}
return(t1);
}
void PrintUsage(void)
{
FILE *a;
char buf[10];
if(!(a=fopen("*","r+")))CleanUpAndExit();
fprintf(a,Version);
fprintf(a,"
Command line options:
\n");
fprintf(a,"-f<file> read fortunes from <file>\n");
fprintf(a,"-l long fortunes (>5 lines) only\n");
fprintf(a,"-w start program up in its own window\n");
fprintf(a,"-s say the fortune with the speech synthesizer\n");
fprintf(a,"
options only valid when -w is also used:
\n");
fprintf(a,"-i start program up as an icon\n");
fprintf(a,"-t use a tiny form of the icon\n");
fprintf(a,"-n<number> display fortune <number>\n");
fprintf(a,"-d<number> delay for <number> seconds between each fortune\n");
fprintf(a,"-x<number> put the window at <number> pixels across\n");
fprintf(a,"-y<number> put the window at <number> pixels down the screen\n");
fprintf(a,"-p<number> as above - kept for compatibility\n");
fprintf(a,"-c<number> set background colour (good in WB2.0!)\n");
fprintf(a,"-m<number> maximum size of window <number> pixels high\n");
fprintf(a,"-o[dcmt] set up the clock display:\n");
fprintf(a," d - display the date\n");
fprintf(a," c - display the time\n");
fprintf(a," m - display available CHIP and FAST memory\n");
fprintf(a," t - display total available memory\n");
fprintf(a,"-q quit after a delay\n");
fprintf(a,"\n
Keys when the fortune window is active:
\n");
fprintf(a,"p print the displayed fortune\n");
fprintf(a,"l toggle long fortunes mode\n");
fprintf(a,"n select a numbered fortune\n");
fprintf(a,"s say the displayes fortune\n");
fprintf(a,"i iconise/deiconise the window\n");
fprintf(a,"q quit the program\n");
fprintf(a,"other display a new fortune\n");
fprintf(a,"\n\n\n
Tool types for the fortune tool
\n");
fprintf(a,"DEFAULT=f set default data file to f\n");
fprintf(a,"DELAY=d set delay to d seconds\n");
fprintf(a,"COLOUR=c set background colour (note English spelling!)\n");
fprintf(a,"FONT=f/s set font to font f at size s, e.g. topaz/8\n");
fprintf(a,"FLAGS=TINY use a tiny form of the icon\n");
fprintf(a,"FLAGS=SPEAK set speech on\n");
fprintf(a,"FLAGS=ICON start up as an icon\n");
fprintf(a,"FLAGS=LONG long fortunes only\n");
fprintf(a,"FLAGS=QUIT quit after a delay\n");
fprintf(a,"FLAGS=CLOCK display the time\n");
fprintf(a,"FLAGS=DATE display the date\n");
fprintf(a,"FLAGS=ALLMEM display available FAST and CHIP memory\n");
fprintf(a,"FLAGS=TOTALMEM display total available memory\n");
fprintf(a,"The above flags can be combined, e.g. FLAGS=SPEAK|ICON\n");
fclose(a);
}
/* write a single line of text */
int yposition=0;
VOID WrtConsole(string,len)
STRPTR string;
ULONG len;
{
if(!yposition)yposition=ConsoleWindow->BorderTop+sysfont->tf_YSize*2;
Move(ConsoleWindow->RPort,5,yposition);
Text(ConsoleWindow->RPort,string,len);
yposition+=sysfont->tf_YSize;
}
/*
* Message printing routine
* Prints a SINGLE LINE (for the time being) message in a slab
*/
char msg_buf[MAXSIZE];
void Message(char *a)
{
char *i,*j;
yposition=0;
SetAPen(ConsoleWindow->RPort,colour);
SetBPen(ConsoleWindow->RPort,colour);
RectFill(ConsoleWindow->RPort,
ConsoleWindow->BorderLeft,
ConsoleWindow->BorderTop,
ConsoleWindow->Width-ConsoleWindow->BorderRight-1,
ConsoleWindow->Height-ConsoleWindow->BorderBottom-1);
SetAPen(ConsoleWindow->RPort,1);
for(i=a,j=a;;j++)
{
if(*j=='\n'||!*j)
{
char c;
c=*j; *j=0;
WrtConsole(i,j-i);
if(!(*(i=j)=c))break;
i++;
}
}
}
struct TextFont *GFont(char *buf) /* font in form "font/size" */
{
int i,size;
char buf2[30],*s=NULL;
struct TextFont *tfont;
struct TextAttr ta;
for(i=0;i<strlen(buf);i++)
{
if(buf[i]=='/')
{
buf[i]=NULL;s=buf+i+1;break;
}
}
if(!s)return(NULL);
strcpy(buf2,buf);
strcat(buf2,".font");
size=atoi(s);
if(!(DiskfontBase=OpenLibrary("diskfont.library",0L)))return(NULL);
ta.ta_Name=buf2;
ta.ta_YSize=size;
ta.ta_Flags=FPF_DISKFONT;
ta.ta_Style=FS_NORMAL;
tfont=(struct TextFont *)OpenDiskFont(&ta);
CloseLibrary(DiskfontBase);
return(tfont);
}
VOID OpenAll()
{
if(!(IntuitionBase=OpenLibrary("intuition.library",0)))
Panic(1,"unable to open intuition.library\n");
if(!(GfxBase=OpenLibrary("graphics.library",0)))
Panic(1,"unable to open graphics.library\n");
if(!(IconBase=OpenLibrary("icon.library",0)))
Panic(1,"unable to open icon.library\n");
ReqToolsBase=OpenLibrary(REQTOOLSNAME,REQTOOLSVERSION);
}
VOID CreateConsole(x,y,w,h)
SHORT x,y,w,h;
{
struct Gadget *g;
int xo,i;
if(ConsoleOpen==TRUE)
return;
ConNewWindow.LeftEdge=x; ConNewWindow.TopEdge=y;
ConNewWindow.Width=w; ConNewWindow.Height=h;
if((ConsoleWindow=OpenWindow(&ConNewWindow))==NULL)
Panic(1,"can't open window\n");
xo=(tiny&&back) ? TINYXOFFSET:XOFFSET;
for(i=0,g=&LeftGadg;g;g=g->NextGadget)
g->LeftEdge=xo+16*i++;
clockpos=xo+16*i+10;
AddGList(ConsoleWindow,&LeftGadg,0,-1,NULL);
if(customfont)
SetFont(ConsoleWindow->RPort,customfont)
ConsoleOpen=TRUE;
}
VOID CleanUpConsole()
{
struct Message *msg;
if(ConsoleOpen)
{
ConsoleOpen=FALSE;
if(ConsoleWindow!=NULL)
{
while(msg=GetMsg(ConsoleWindow->UserPort))ReplyMsg(msg);
CloseWindow(ConsoleWindow);
}
}
}
VOID CleanUp()
{
TimerStop();
SND_Shutdown();
CleanUpConsole();
if(customfont)CloseFont(customfont);
if(GfxBase)CloseLibrary(GfxBase);
if(IntuitionBase)CloseLibrary(IntuitionBase);
if(IconBase)CloseLibrary(IconBase);
if(ReqToolsBase)CloseLibrary(ReqToolsBase);
}
VOID CleanUpAndExit()
{
CleanUp();
exit(TRUE);
}
/*
void WaitForIDCMP(msg)
ULONG msgc;
{
struct IntuiMessage *msg;
waitlp: WaitPort(ConsoleWindow->UserPort);
msg=(struct IntuiMessage *)GetMsg(ConsoleWindow->UserPort);
ReplyMsg((struct Message *)msg);
if(msg->Class!=msgc)goto waitlp;
}
*/
VOID Iconise()
{
back=1;
iy=ConsoleWindow->TopEdge;
CleanUpConsole();
CreateConsole(ix,iy,tiny?TINYICONLEN+(clock?CLOCKLEN:0):
ICONLEN+(clock?CLOCKLEN:0),9);
if((ConsoleWindow->BorderTop-9)!=0)
{
SizeWindow(ConsoleWindow,0,
ConsoleWindow->BorderTop-9);
Delay(5);
}
SetWindowTitles(ConsoleWindow,tiny?NULL:ICONTITLE,-1);
}
VOID DeIconise()
{
back=0;
iy=min(ConsoleWindow->TopEdge,180);
ix=ConsoleWindow->LeftEdge;
CleanUpConsole();
}
void DoAnother(void)
{
if(back)
{
DeIconise();
}
Ticks=0;
Again=TRUE;
return;
}
int fortune_number=-1,current_fortune=0;
unsigned long number;
VOID GetNumber()
{
char buf[80];
FILE *a;
long num;
if(ReqToolsBase)
{
ULONG tags[]={ RTEZ_DefaultResponse,1,TAG_END};
retr1: if(!rtGetLong(&num,"Get fortune number",NULL,
RTGL_ShowDefault,FALSE,
TAG_END))
{
if(rtEZRequest("You entered nothing.\n"
"There are %ld fortunes.","Try again|Sorry",NULL,
(struct TagItem *)tags,number))goto retr1;
}
else
fortune_number=num;
}
else
{
if(!(a=fopen("CON:0/0/640/40/Which fortune would you like?","r+")))
Panic(1,"unable to open getnumber window\n");
fgets(buf,40,a);
fortune_number=atoi(buf);
}
fclose(a);
}
/*
* Alarm states:
*
* 0 no alarm (goes to 1 when alarm set by user)
* 1 alarm set (alarm snds and goes to 0 when alarm time = clock time)
*
*/
int alarm_hour,alarm_min;
int alarm_state=0;
VOID SetAlarm()
{
FILE *a;
char buf[44];
int n;
if(!clock)
{
Panic(0,"clock not active (run with -oc or FLAGS=CLOCK)");
return;
}
SND_Init();
if(!ReqToolsBase)
{
if(!(a=fopen("CON:0/0/640/40/Enter the time (HH:MM):","r+")))
Panic(1,"unable to open setalarm window\n");
}
do
{
if(ReqToolsBase)
{
*buf='\0';
rtGetString(buf,40,"Enter time (HH:MM):",NULL,TAG_END);
}
else
{
fgets(buf,40,a);
}
n=sscanf(buf,"%d:%d",&alarm_hour,&alarm_min);
} while(n<2);
fclose(a);
alarm_state=1;
clock |= CF_CLOCK;
}
void WriteFortune(char *fl,char *str)
{
FILE *a;
if(!(a=fopen(fl,"w")))return;
if(ConsoleOpen)ModifyIDCMP(ConsoleWindow,NULL);
fputs(str,a);
fclose(a);
if(ConsoleOpen)ModifyIDCMP(ConsoleWindow,IDCMPFLAGS);
}
VOID WriteClock()
{
static char clockbuf[80];
static char buf[20];
struct tm *ts;
static long t;
ULONG chipmem,fastmem;
char *i;
int j=0,lim;
time(&t);
ts=localtime(&t);
/* There is a limit on how many options the icon can show */
lim=back?2:8;
*clockbuf=*buf=NULL;
if(clock & CF_CLOCK)
{
if(j++>lim)goto too_many;
sprintf(buf,"%d:%2d:%2d",ts->tm_hour,ts->tm_min,ts->tm_sec);
switch(alarm_state)
{
case 0:break;
case 1:
if(alarm_hour==ts->tm_hour && alarm_min==ts->tm_min)
{
SND_Play(SoundData,SOUND_LEN,400);
alarm_state=0;
}
break;
default:Panic(1,"Bad internal alarm state");
}
for(i=buf;*i;i++)if(*i==' ')*i='0';
strcat(clockbuf,buf);if(j++>lim)goto too_many;
}
if(clock & CF_DATE)
{
if(j++>lim)goto too_many;
sprintf(buf," %d:%s:%d",ts->tm_mday,
month_names[ts->tm_mon],ts->tm_year%100);
strcat(clockbuf,buf);if(j++>lim)goto too_many;
}
if(clock & CF_TOTALMEM)
{
if(j++>lim)goto too_many;
chipmem=AvailMem(0L)>>10; /* show in K */
sprintf(buf," Mem:%ld",chipmem);
strcat(clockbuf,buf);
}
if(clock & CF_ALLMEM)
{
if(j++>lim)goto too_many;
chipmem=AvailMem(MEMF_CHIP)>>10;
fastmem=AvailMem(MEMF_FAST)>>10;
sprintf(buf," C%ld/F%ld",chipmem,fastmem);
strcat(clockbuf,buf);
}
too_many:
strcat(clockbuf," ");
SetFont(ConsoleWindow->RPort,topazfont);
if(back)
{
SetAPen(ConsoleWindow->RPort,1);
SetBPen(ConsoleWindow->RPort,0);
Move(ConsoleWindow->RPort,clockpos,8);
}
else
Move(ConsoleWindow->RPort,5,ConsoleWindow->Height-10);
Text(ConsoleWindow->RPort,clockbuf,strlen(clockbuf));
if(customfont)SetFont(ConsoleWindow->RPort,customfont);
}
void About()
{
rtEZRequestTags("Fortune 3.25, by Jim Finnis (March 1993)\n"
"Thanks to Nico Francois for ReqTools,\n"
"to Bach, Cardiacs and R.E.M. for sonic\n"
"debugging assistance, and to Shona\n"
"for not minding when I crawl into bed\n"
"at 4 AM.\n"
" -- White the Ergodic Archwizard","Cosmic|Virtual|Mu",
NULL,NULL,
RT_ReqPos,REQPOS_CENTERSCR,
TAG_END);
}
VOID IDCMP_Handler()
{
SHORT flag=TRUE;
struct IntuiMessage *msg;
struct Gadget *g;
int c,code;
USHORT id;
ULONG signals,consolebit,timerbit=0L;
consolebit=1L<<ConsoleWindow->UserPort->mp_SigBit;
if(timerport)timerbit=1<<timerport->mp_SigBit;
while(flag)
{
struct Message *tmsg;
signals=Wait(consolebit | timerbit);
while(msg=(struct IntuiMessage *)GetMsg(ConsoleWindow->UserPort))
{
c=msg->Class;
g=(struct Gadget *)msg->IAddress; /* only valid for gadg. */
code=msg->Code;
ReplyMsg((struct Message *)msg);
switch(c)
{
case CLOSEWINDOW:
flag=FALSE;
break;
case VANILLAKEY:
switch(code)
{
case 'p':
print=1;
flag=FALSE;
DoAnother();
break;
case 's':
flag=FALSE;
DoAnother();
speak=!speak;
break;
case 'l':
flag=FALSE;
DoAnother();
longflag=!longflag;
break;
case 'q':
if(ReqToolsBase)
{
if(rtEZRequest("Really quit this awesome program?",
"Way|No way!",NULL,NULL))flag=FALSE;
}
else
flag=FALSE;
break;
case 'i':
if(back)
DeIconise();
else
{
Iconise();
break;
}
Ticks=0;
flag=FALSE;
Again=TRUE;
break;
case 'n':
GetNumber();
flag=FALSE;
DoAnother();
break;
case 'a':
SetAlarm();
break;
case '?':About();break;
default:
flag=FALSE;
DoAnother();
break;
}
break;
case GADGETDOWN:
id=g->GadgetID;
switch(id)
{
case 0: /* left */
fortune_number=current_fortune-1;
fortune_number=max(fortune_number,0);
flag=FALSE; DoAnother(); break;
case 1: /* rand */
flag=FALSE; DoAnother(); break;
case 2: /*right */
fortune_number=current_fortune+1;
fortune_number=min(fortune_number,(number-1));
flag=FALSE; DoAnother(); break;
case 3: /* pause */
break;
case 4: /* iconify */
if(back)
DeIconise();
else
{
Iconise();break;
}
Ticks=0;flag=FALSE; Again=TRUE;
break;
default:Panic(1,"Funny gadget - %d\n!",id);
}
default:
break;
} /* switch */
if(!ConsoleOpen)
break;
} /* while */
while(tmsg=GetMsg(timerport))
{
if(clock&&ConsoleOpen)WriteClock();
TimerGo(); /* and kick it again */
if(back||PauseGadg.Flags & SELECTED)break;
if(Ticks++>del){Ticks=0;Again=TRUE;flag=FALSE;}
}
} /* while */
}
void __regargs main(int argc,char *argv[])
{
char *inf=infile;
int ow=0,w,oh=0,r,i,h,slen;
char buf[MAXSIZE],ermintrude[80];
char *str;
char snum[30];
int maxsize,maxwinsize,scrwidth=640,scrheight=200;
int winposx=30,winposy=0,usageflag=0,quit_delay=0;
unsigned long pos,t;
BPTR a;
FILE *fa;
struct WBArg *wbarg;
struct WBStartup *WBenchMsg;
struct Screen *wbscr;
OpenAll();
if(wbscr=OpenWorkBench())
{
scrwidth=wbscr->Width;
scrheight=wbscr->Height;
}
topazfont=sysfont=GfxBase->DefaultFont;
maxsize=maxwinsize=scrheight;
srand(time(&t));
if(argc)
{
wb_exec=0;
if((argc>1) && (!strcmp(argv[1],"?")))
usageflag=1;
for(i=1;i<argc;++i)
{
switch(argv[i][1])
{
case 'o':
case 'O': /* what clock stuff do we get?
Note that only the first two of these have
any effect */
for(str=argv[i]+2;*str;str++)
{
switch(*str)
{
case 'c':clock |= CF_CLOCK;break;
case 'd':clock |= CF_DATE;break;
case 'm':clock |= CF_ALLMEM;break;
case 't':clock |= CF_TOTALMEM;break;
}
}
break;
case 'q':
case 'Q':
quit_delay=1;
break;
case 'n':
case 'N':
fortune_number=atoi(argv[i]+2);
break;
case 'f':
case 'F':
strcpy(ermintrude,argv[i]+2);
inf=ermintrude;
break;
case 'l': /* >10 line fortunes only */
case 'L':
longflag=1;break;
case 'i': /* Iconise */
case 'I':
back=1;
break;
case 't': /* tiny icon */
case 'T':
tiny=1;break;
case 'w': /* Window it anyway. */
case 'W':
win=1;
break;
case 'c':
case 'C':
colour=atoi(argv[i]+2);
break;
case 'd': /* delay */
case 'D':
del=atoi(argv[i]+2);
del=max(2,del);
break;
case 'm': /* maxsize of window */
case 'M':
maxsize=atoi(argv[i]+2);
maxsize=min(maxwinsize,maxsize);
maxsize=max(20,maxsize);
break;
case 's': /* speech (titter) */
speak=1;
break;
case 'y': /* position of window */
case 'Y':
case 'p':
case 'P':
winposy=atoi(argv[i]+2);
winposy=min(maxwinsize-20,winposy);
winposy=max(0,winposy);
break;
case 'x': /* position of window */
case 'X':
winposx=atoi(argv[i]+2);
winposx=min(640-ICONLEN+CLOCKLEN,winposx);
winposx=max(0,winposx);
break;
case 'H':
case 'h':
case '?':
usageflag=1;
break;
}
}
}
else /* WB Startup */
{
struct DiskObject *dobj;
char *quop;
char **toolarray;
win=1;
WBenchMsg=(struct WBStartup *)argv;
wbarg=WBenchMsg->sm_ArgList;
if((*wbarg->wa_Name)&&(dobj=GetDiskObject(wbarg->wa_Name)))
{
toolarray=(char **)dobj->do_ToolTypes;
if(quop=(char *)FindToolType(toolarray,"DEFAULT"))
{
strcpy(ermintrude,quop);
inf=ermintrude;
}
if(quop=(char *)FindToolType(toolarray,"FONT"))
{
strcpy(buf,quop);
if(customfont=GFont(buf))
sysfont=customfont;
}
if(quop=(char *)FindToolType(toolarray,"DELAY"))
{
del=atoi(quop);
del=max(del,1);
}
if(quop=(char *)FindToolType(toolarray,"COLOUR"))
colour=atoi(quop);
if(quop=(char *)FindToolType(toolarray,"FLAGS"))
{
if(MatchToolValue(quop,"SPEAK"))
speak=1;
if(MatchToolValue(quop,"LONG"))
longflag=1;
if(MatchToolValue(quop,"TINY"))
tiny=1;
if(MatchToolValue(quop,"ICON"))
back=1;
if(MatchToolValue(quop,"QUIT"))
quit_delay=1;
if(MatchToolValue(quop,"CLOCK"))
clock|=CF_CLOCK;
if(MatchToolValue(quop,"TOTALMEM"))
clock|=CF_TOTALMEM;
if(MatchToolValue(quop,"ALLMEM"))
clock|=CF_ALLMEM;
if(MatchToolValue(quop,"DATE"))
clock|=CF_DATE;
}
FreeDiskObject(dobj);
}
if(WBenchMsg->sm_NumArgs>=2)
{
wbarg=WBenchMsg->sm_ArgList+1;
olddir=-1;
if((wbarg->wa_Lock)&&(*wbarg->wa_Name))
olddir=CurrentDir(wbarg->wa_Lock);
inf=wbarg->wa_Name;
if((*wbarg->wa_Name)&&
(dobj=GetDiskObject(wbarg->wa_Name)))
{
toolarray=(char **)dobj->do_ToolTypes;
if(quop=(char *)FindToolType(toolarray,
"FILETYPE"))
{
if(strcmp(quop,"Fortunes"))
inf=NULL;
}
else
inf=NULL;
FreeDiskObject(dobj);
}
}
if(!inf)
{
DisplayBeep(NULL);
CleanUpAndExit();
}
}
if(quit_delay)back=0; /* can't have an iconised quitter! */
if(del<0)
del=quit_delay?60:TIMELIM;
iy=winposy;
ix=winposx;
if(usageflag)
{
PrintUsage();
CleanUpAndExit();
}
/* This is the beginning of the main loop. The file is reopened, because
rewind() in Lattice's library is flaky. */
giles:
NiceUp();
if(!(a=Open(inf,MODE_OLDFILE)))
Panic(1,"File not found - %s\n",inf);
/* read in the huffman table */
loadhuffman(a);
/* How many fortunes are there? */
number=readlong(a);
if(number<=0) Panic(1,"Bad data file\n");
/* Get a random one */
current_fortune = fortune_number<0 ?
rand()%((unsigned int)number):fortune_number;
if(current_fortune>=number)
{
Panic(0,"Fortune %d out of range, there are %d fortunes\n",
current_fortune,number);
fortune_number=-1;
goto giles;
}
sprintf(snum,"Fortune number #%d",current_fortune);
ConNewWindow.Title=snum;
ConNewWindow.MaxHeight=maxsize;
/* Get the position */
Seek(a,4*(current_fortune+1)+20*16,OFFSET_BEGINNING);
pos=readlong(a);
/* Grab it */
Seek(a,pos,OFFSET_BEGINNING);
readstring(&buf,MAXSIZE,a);
Close(a);
str=uncompress(buf);
/* How many lines of text in the fortune? */
slen=strlen(str);
for(r=0,i=0;i<slen;i++) if(str[i]=='\n') r++;
if((fortune_number<0) && longflag && (r<=5))
{
fortune_number=-1;
goto giles;
}
if(argc) /* If run from CLI */
{
if(!win)
{
fa=fopen("*","r+");
if(fa==NULL) CleanUpAndExit();
fprintf(fa,"%s",str);
if(speak)WriteFortune("speak:",str);
fclose(fa);
CleanUpAndExit(0);
}
}
/* Work out the size of the window (use default font for 2.0) */
h=(sysfont->tf_YSize)*(r+2)+22;
if(h>maxsize)
{
if(fortune_number>0)
Panic(0,"fortune too tall\n");
fortune_number=-1;
goto giles;
}
/* Is it too wide? */
if((w=(GetMaxTextLen(sysfont,str)+10))>(scrwidth-5))
{
if(fortune_number>0)
Panic(0,"fortune too wide\n");
fortune_number=-1;
goto giles;
}
w=max(w,MINWIDTH);
/* Start the inexorable march of time.... */
if(!timeropen&&win)StartTimerDevice();
if(ConsoleOpen)
{
int deltah,deltaw;
if(!back)
{
int p,q;
deltah=h-oh; deltaw=w-ow;
p=ConsoleWindow->LeftEdge+ConsoleWindow->Width+deltaw;
q=ConsoleWindow->TopEdge+ConsoleWindow->Height+deltah;
p=p>scrwidth?scrwidth-p:0;
q=q>maxwinsize?maxwinsize-q:0;
if(p||q)
MoveWindow(ConsoleWindow,p,q);
SizeWindow(ConsoleWindow,deltaw,deltah);
SetWindowTitles(ConsoleWindow,snum,-1);
Delay(5);
}
}
else
{
if(back)
{
CreateConsole(ix,iy,tiny?TINYICONLEN+(clock?CLOCKLEN:0):
ICONLEN+(clock?CLOCKLEN:0),9);
if((ConsoleWindow->BorderTop-9)!=0)
{
SizeWindow(ConsoleWindow,0,
ConsoleWindow->BorderTop-9);
Delay(5);
}
SetWindowTitles(ConsoleWindow,tiny?NULL:ICONTITLE,-1);
}
else
{
if(iy+h>maxwinsize)iy=maxwinsize-h;
if(ix+w>scrwidth)ix=scrwidth-w;
CreateConsole(ix,iy,w,h);
if((ConsoleWindow->BorderTop-9)!=0)
{
SizeWindow(ConsoleWindow,0,
ConsoleWindow->BorderTop-9);
Delay(5);
}
}
}
if(!back)
Message(str);
NiceDown();
fortune_number=-1;
if(quit_delay) /* quit after a delay */
{
Delay(del*TICKS_PER_SECOND);
CleanUpAndExit();
}
IDCMP_Handler();
if(speak)
{
speak=0;
WriteFortune("speak:",str);
}
if(print)
{
print=0;
WriteFortune("prt:","\n");WriteFortune("prt:",str);
}
if(Again)
{
Again=FALSE;
oh=h;ow=w;
goto giles;
}
CleanUpAndExit();
}